﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using TravelLib;
using System.Reflection;
using MultiAgentLib;
using DatasourceParser;


namespace JadeTravelAgent
{
    public partial class TravelForm : Form
    {
        private Request _currentRequest;
        private List<string> _airportNames;
        private int[,] _destinationGraph;
        private List<String> _flightClasses;
        static  List<List<int>> routeList = new List<List<int>>();
        static int maxx;
        public TravelForm()
        {
            InitializeComponent();
            InitForm();
        }

        private void InitForm()
        {
            this._currentRequest = new Request();           
            _destinationGraph = Utils.DestinationGraph;
            _airportNames = AirportManager.GetAirportNameList();
            _flightClasses = new List<string>();
            _flightClasses.Add(StringEnum.GetStringValue(TravelClassEnum.BUSSINESS_CLASS));
            _flightClasses.Add(StringEnum.GetStringValue(TravelClassEnum.ECONOMY_CLASS));
            _flightClasses.Add(StringEnum.GetStringValue(TravelClassEnum.FIRST_CLASS));
            comboBoxArrival.DataSource = AirportManager.GetAirportNameList();
            comboBoxDeparture.DataSource = AirportManager.GetAirportNameList();
            comboBoxClass.DataSource = _flightClasses;
            maxx = AirportManager.GetNumberOfAirports();
            new Parser().Setup();
        }
        private void buttonSubmit_Click(object sender, EventArgs e)
        {
            if (dateTimePickerLeave.Value.Date > dateTimePickerReturn.Value.Date)
            {
                MessageBox.Show("Invalid period");
                return;
            }
            if (string.IsNullOrEmpty(comboBoxDeparture.SelectedValue.ToString()) || string.IsNullOrEmpty(comboBoxArrival.SelectedValue.ToString()))
            {
                MessageBox.Show("Choose departure and arrival");
                return;
            }
            _currentRequest = new Request();
            _currentRequest.NumberOfSeats = (int)numericUpDownSeats.Value;
            _currentRequest.PlaneChange = checkBoxPlaneChange.Checked;
            _currentRequest.StopOver = checkBoxStopover.Checked;
            _currentRequest.UserSetRoute = new Route()
            {
                DepartureAirport = AirportManager.GetAirportByName(comboBoxDeparture.SelectedValue.ToString()),
                DestinationAirport = AirportManager.GetAirportByName(comboBoxArrival.SelectedValue.ToString()),
                DteFrom = dateTimePickerLeave.Value.Date,
                DteTo = dateTimePickerReturn.Value.Date
            };
            _currentRequest.TravelClass = GetTravelClass(comboBoxClass.SelectedValue.ToString());
            //start here by checking all the intermediate routes we must get from the Agents
           
            List<int> visited = new List<int>();           
            visited.Add(_currentRequest.UserSetRoute.DepartureAirport.Index);
            BreadthFirst(_destinationGraph, visited, _currentRequest.UserSetRoute.DestinationAirport.Index);
            _currentRequest.PreIntermediateRoutes = ConvertList(routeList);

            foreach (HashSet<Route> lr in _currentRequest.PreIntermediateRoutes)
            {
                foreach (Route r in lr)
                {
                    _currentRequest.IntermediateRoutes.Add(r);
                }
            }


            if (_currentRequest.IntermediateRoutes == null || _currentRequest.IntermediateRoutes.Count == 0)
                _currentRequest.IntermediateRoutes.Add(_currentRequest.UserSetRoute);
            MASInit.InitAgents(_currentRequest, ref richTextBoxFlights);
 
        }

        private static void BreadthFirst(int[,] graph, List<int> visited, int END)
        {
            List<int> nodes = new List<int>();
            int lastv = visited.Last();
            for (int i = 0; i < maxx; i++)
            {
                if (graph[i, lastv] == 1)
                {
                    nodes.Add(i);
                }
            }

            // examine adjacent nodes
            foreach (var node in nodes)
            {
                if (visited.Contains(node))
                {
                    continue;
                }
                if (node == END)
                {
                    visited.Add(node);
                    List<int> vv = new List<int>();
                    vv.AddRange(visited);
                    routeList.Add(vv);
                    visited.Remove(visited.Last());
                    break;
                }
            }

            // in breadth-first, recursion needs to come after visiting adjacent nodes
            foreach (var node in nodes)
            {
                if (visited.Contains(node) || node == END)
                {
                    continue;
                }
                visited.Add(node);
                BreadthFirst(graph, visited, END);
                visited.Remove(visited.Last());
            }
        }
        private static List<HashSet<Route>> ConvertList(List<List<int>> indexList)
        {
            List<HashSet<Route>> routeList = new List<HashSet<Route>>();
            HashSet<Route> helpList = new HashSet<Route>();
            List<Airport> airportList = new List<Airport>(); 
            Route myRoute = new Route();

            foreach (List<int> l in indexList)
            {
                for (int i=0;i<l.Count;i++)
                {
                    myRoute.DepartureAirport= AirportManager.GetAirportByIndex(i);
                    //if (i+1<l.Count)
                    //{   
                        myRoute.DestinationAirport=AirportManager.GetAirportByIndex(i+1);

                    //}
                    helpList.Add(myRoute);
                    
                }
                routeList.Add(helpList);

            }
            return routeList;
        }

        private TravelClassEnum GetTravelClass(string s)
        {
            Type type = TravelClassEnum.BUSSINESS_CLASS.GetType();
            foreach (FieldInfo fi in type.GetFields())
            {
                StringValue[] attrs =
                   fi.GetCustomAttributes(typeof(StringValue),
                                           false) as StringValue[];
                if (attrs.Length > 0 && s.CompareTo(attrs[0].Value) == 0)
                {
                    if (fi.Name == TravelClassEnum.BUSSINESS_CLASS.ToString())
                        return TravelClassEnum.BUSSINESS_CLASS;
                    if (fi.Name == TravelClassEnum.ECONOMY_CLASS.ToString())
                        return TravelClassEnum.ECONOMY_CLASS;
                    return TravelClassEnum.FIRST_CLASS;
                }
            }
            return TravelClassEnum.ECONOMY_CLASS;
        }


    }
}
